package com.laomuji.android.mvvm.utils

import android.graphics.Color
import android.graphics.Typeface
import android.text.SpannableString
import android.text.Spanned
import android.text.TextPaint
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.text.style.UnderlineSpan
import android.view.View
import android.widget.TextView

/**
 * 为TextView添加多个文字区域
 * @author laomuji666
 * @since 2024/2/21
 */
class SpanUtil {
    companion object {
        /**
         *
         * 为TextView的Span添加点击事件
         * TextView必须调用[TextView.setMovementMethod] 传入 [LinkMovementMethod.getInstance]
         * 使TextView可以响应局部的点击事件
         */
        fun initTextView(textView: TextView) {
            val linkMovementMethod = LinkMovementMethod.getInstance()
            if(textView.movementMethod != linkMovementMethod){
                textView.movementMethod = LinkMovementMethod.getInstance()
            }
        }
    }

    /**
     * 每个文字区域的属性
     */
    data class Span(
        val text: String = "",
        val color: Int = Color.TRANSPARENT,
        val hasUnderLine: Boolean = false,
        val hasBold: Boolean = false,
        val hasItalic: Boolean = false,
        val clickListener: Runnable? = null,
    )

    /**
     * 没有下划线的点击Span
     */
    private abstract class NoUnderlineClickableSpan : ClickableSpan() {
        override fun updateDrawState(ds: TextPaint) {
            ds.isUnderlineText = false
        }
    }

    /**
     * 存放所有Span
     */
    private val spanList: ArrayList<Span> = ArrayList()

    /**
     * 添加Span到后方
     */
    fun addSpan(span: Span) = spanList.add(span)

    /**
     * 构建SpannableString
     * 构建的顺序为spanList的顺序
     */
    fun build(): SpannableString {
        //先创建文字
        val builder: StringBuilder = StringBuilder()
        for (span in spanList) {
            builder.append(span.text)
        }
        val spannableString = SpannableString(builder.toString())

        var startPos = 0
        var endPos: Int
        for (span in spanList) {
            //更新结束位置
            endPos = startPos + span.text.length

            //设置文字颜色
            spannableString.setSpan(
                ForegroundColorSpan(span.color),
                startPos,
                endPos,
                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
            )

            //设置文字点击事件
            if (span.clickListener != null) {
                spannableString.setSpan(
                    object : NoUnderlineClickableSpan() {
                        override fun onClick(widget: View) {
                            span.clickListener.run()
                        }
                    }, startPos, endPos, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
                )
            }

            //设置下划线
            if (span.hasUnderLine) {
                spannableString.setSpan(
                    UnderlineSpan(),
                    startPos,
                    endPos,
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
                )
            }

            //设置加粗和倾斜
            if (span.hasBold || span.hasItalic) {
                val styleSpan =
                    StyleSpan((if (span.hasBold) Typeface.BOLD else 0) or if (span.hasItalic) Typeface.ITALIC else 0)
                spannableString.setSpan(
                    styleSpan,
                    startPos,
                    endPos,
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
                )
            }

            //更新位置
            startPos = endPos
        }

        return spannableString
    }
}